package pl.wroc.pwr.nn;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class TestNeuralNetwork {

	private static final int hidden = 7;
	private static final float theta = 0.1f;
	private static final int liczbaEpok = 1000;
	private int positive = 0;
	private int input;
	private int output;
	private ArrayList<String> labels;
	private NeuralNetwork network;

	public TestNeuralNetwork(String daneUczace, String daneTestowe, int input,
			int output) throws IOException {

		this.input = input;
		this.output = output;

		network = new NeuralNetwork(this.input, this.output, hidden, theta);

		ucz(liczbaEpok, daneUczace);
		testuj(daneTestowe);

	}

	private void ucz(int liczbaEpok, String nazwapliku) throws IOException {

		TrainingVectors sequence = getSequence(nazwapliku);
		labels = sequence.getLabels();

		for (int l = 0; l < liczbaEpok; l++) {
			TrainingVectors tempSequence = new TrainingVectors(sequence);
			while (!tempSequence.isEmpty()) {
				LabeledVector vec = tempSequence.detachRandomVector();

				String label = vec.getLabel();

				int indexOfOutput = labels.indexOf(label);
				double[] out = generateOutput(indexOfOutput);

				InputExample example = new InputExample(vec.getValues(), out);

				network.runBackPropagationLearing(example);

			}
		}
	}

	private double[] generateOutput(int index) {
		double[] out = new double[output];
		for (int i = 0; i < output; i++) {
			if (i == index) {
				out[i] = 1;
			} else {
				out[i] = 0;
			}
		}
		return out;
	}

	/*
	 * pobiera z pliku
	 */
	private TrainingVectors getSequence(String file) throws IOException {
		TrainingVectors learningSequence = new TrainingVectors();
		int liczbaLini = numberOfLines(file);

		BufferedReader br = new BufferedReader(new FileReader(file));

		for (int i = 0; i < liczbaLini; i++) {

			String f = br.readLine();
			StringTokenizer st = new StringTokenizer(f, ",");
			double[] featureVec = new double[input];

			for (int j = 0; j < input; j++) {
				featureVec[j] = Double.valueOf(st.nextToken());
			}
			String label = st.nextToken();

			LabeledVector vec = new LabeledVector(featureVec, label);

			learningSequence.add(vec);
		}
		return learningSequence;

	}

	private void testuj(String file) throws IOException {

		int linie = numberOfLines(file);

		BufferedReader br = new BufferedReader(new FileReader(file));
		for (int i = 0; i < linie; i++) {
			String f = br.readLine();
			StringTokenizer st = new StringTokenizer(f, ",");

			double[] in = new double[input];
			for (int j = 0; j < input; j++) {
				in[j] = Double.valueOf(st.nextToken());
			}

			String realLabel = st.nextToken();

			InputExample ex = new InputExample(in, new double[1]);

			int ce = network.check(ex);

			if (labels.get(ce).equals(realLabel)) {
				positive++;
				//System.out.println("Dla ciagu testujacego " + i
				//		+ " poprawnie rozpoznano " + realLabel);
			}
		}

		System.out.println("Rozponano poprawnie: " + positive + "/" + linie);
	}

	private int numberOfLines(String file) throws IOException {
		int linie = 0;
		BufferedReader br = new BufferedReader(new FileReader(file));

		while (br.readLine() != null) {
			linie++;
		}
		br.close();
		return linie;
	}

	public static void main(String[] agrs) throws IOException {
		int input = Integer.valueOf(agrs[2]);
		int output = Integer.valueOf(agrs[3]);
		new TestNeuralNetwork(agrs[0], agrs[1], input, output);
	}

}